using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using System.Text.Json;
using Serilog.Events;
using System.ComponentModel.DataAnnotations;

namespace WeatherSystem.API.Controllers
{
    /// <summary>
    /// 日志查询API控制器
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    public class LogsController : ControllerBase
    {
        private readonly ILogger<LogsController> _logger;
        private readonly IWebHostEnvironment _environment;

        public LogsController(ILogger<LogsController> logger, IWebHostEnvironment environment)
        {
            _logger = logger;
            _environment = environment;
        }

        /// <summary>
        /// 查询日志文件
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> GetLogs(
            [FromQuery] string? level = null,
            [FromQuery] DateTime? startDate = null,
            [FromQuery] DateTime? endDate = null,
            [FromQuery] string? search = null,
            [FromQuery] int limit = 100,
            [FromQuery] int skip = 0)
        {
            try
            {
                var logs = await ReadLogFiles(level, startDate, endDate, search, limit, skip);
                return Ok(new
                {
                    Total = logs.Count,
                    Data = logs,
                    Filters = new
                    {
                        Level = level,
                        StartDate = startDate,
                        EndDate = endDate,
                        Search = search,
                        Limit = limit,
                        Skip = skip
                    }
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "查询日志失败");
                return StatusCode(500, new { Message = "查询日志失败", Error = ex.Message });
            }
        }

        /// <summary>
        /// 获取日志级别统计
        /// </summary>
        [HttpGet("stats")]
        public async Task<IActionResult> GetLogStats(
            [FromQuery] DateTime? startDate = null,
            [FromQuery] DateTime? endDate = null)
        {
            try
            {
                var stats = await GetLogLevelStats(startDate, endDate);
                return Ok(stats);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取日志统计失败");
                return StatusCode(500, new { Message = "获取日志统计失败", Error = ex.Message });
            }
        }

        /// <summary>
        /// 下载日志文件
        /// </summary>
        [HttpGet("download")]
        public async Task<IActionResult> DownloadLogs(
            [FromQuery] DateTime? date = null,
            [FromQuery] string type = "all") // all, errors
        {
            try
            {
                var targetDate = date ?? DateTime.Today;
                var fileName = type == "errors" 
                    ? $"weather-system-errors-{targetDate:yyyyMMdd}.log"
                    : $"weather-system-{targetDate:yyyyMMdd}.log";

                var filePath = Path.Combine("logs", fileName);
                
                if (!System.IO.File.Exists(filePath))
                {
                    return NotFound(new { Message = $"日志文件不存在: {fileName}" });
                }

                var fileBytes = await System.IO.File.ReadAllBytesAsync(filePath);
                return File(fileBytes, "text/plain", fileName);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "下载日志文件失败");
                return StatusCode(500, new { Message = "下载日志文件失败", Error = ex.Message });
            }
        }

        /// <summary>
        /// 测试日志记录
        /// </summary>
        [HttpPost("test")]
        public IActionResult TestLogging([FromBody] TestLogRequest request)
        {
            try
            {
                var level = Enum.Parse<LogLevel>(request.Level, true);
                
                switch (level)
                {
                    case LogLevel.Information:
                        _logger.LogInformation("测试信息日志: {Message} - {TestId}", request.Message, request.TestId);
                        break;
                    case LogLevel.Warning:
                        _logger.LogWarning("测试警告日志: {Message} - {TestId}", request.Message, request.TestId);
                        break;
                    case LogLevel.Error:
                        _logger.LogError("测试错误日志: {Message} - {TestId}", request.Message, request.TestId);
                        break;
                    case LogLevel.Debug:
                        _logger.LogDebug("测试调试日志: {Message} - {TestId}", request.Message, request.TestId);
                        break;
                    default:
                        _logger.LogInformation("测试日志: {Message} - {TestId}", request.Message, request.TestId);
                        break;
                }

                return Ok(new { Message = "测试日志已记录", Level = level, TestId = request.TestId });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "测试日志记录失败");
                return StatusCode(500, new { Message = "测试日志记录失败", Error = ex.Message });
            }
        }

        private async Task<List<LogEntry>> ReadLogFiles(
            string? level, 
            DateTime? startDate, 
            DateTime? endDate, 
            string? search, 
            int limit, 
            int skip)
        {
            var logs = new List<LogEntry>();
            var logsDir = Path.Combine(Directory.GetCurrentDirectory(), "logs");
            
            if (!Directory.Exists(logsDir))
            {
                return logs;
            }

            var logFiles = Directory.GetFiles(logsDir, "weather-system-*.log")
                .OrderByDescending(f => f)
                .Take(7); // 最近7天的日志

            foreach (var file in logFiles)
            {
                try
                {
                    var lines = await System.IO.File.ReadAllLinesAsync(file);
                    foreach (var line in lines)
                    {
                        if (string.IsNullOrWhiteSpace(line)) continue;

                        var logEntry = ParseLogLine(line);
                        if (logEntry == null) continue;

                        // 应用过滤器
                        if (!string.IsNullOrEmpty(level) && !logEntry.Level.Equals(level, StringComparison.OrdinalIgnoreCase))
                            continue;

                        if (startDate.HasValue && logEntry.Timestamp < startDate.Value)
                            continue;

                        if (endDate.HasValue && logEntry.Timestamp > endDate.Value)
                            continue;

                        if (!string.IsNullOrEmpty(search) && !logEntry.Message.Contains(search, StringComparison.OrdinalIgnoreCase))
                            continue;

                        logs.Add(logEntry);
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "读取日志文件失败: {FileName}", file);
                }
            }

            return logs
                .OrderByDescending(l => l.Timestamp)
                .Skip(skip)
                .Take(limit)
                .ToList();
        }

        private LogEntry? ParseLogLine(string line)
        {
            try
            {
                // 尝试解析JSON格式日志
                if (line.StartsWith("{"))
                {
                    var jsonDoc = JsonDocument.Parse(line);
                    var root = jsonDoc.RootElement;

                    return new LogEntry
                    {
                        Timestamp = DateTime.Parse(root.GetProperty("@t").GetString()!),
                        Level = root.GetProperty("@l").GetString()!,
                        Message = root.GetProperty("@m").GetString()!,
                        Exception = root.TryGetProperty("@x", out var ex) ? ex.GetString() : null,
                        SourceContext = root.TryGetProperty("SourceContext", out var sc) ? sc.GetString() : null,
                        TraceId = root.TryGetProperty("TraceId", out var tid) ? tid.GetString() : null,
                        Properties = root.TryGetProperty("Properties", out var props) ? props.GetRawText() : null
                    };
                }

                // 回退到文本格式解析
                var parts = line.Split("] ", 3);
                if (parts.Length >= 3)
                {
                    var timestampLevel = parts[0].TrimStart('[');
                    var timestampParts = timestampLevel.Split(' ');
                    if (timestampParts.Length >= 3)
                    {
                        var timestamp = DateTime.Parse(timestampParts[0] + " " + timestampParts[1]);
                        var level = timestampParts[2].Trim();
                        var message = parts[2];

                        return new LogEntry
                        {
                            Timestamp = timestamp,
                            Level = level,
                            Message = message,
                            SourceContext = parts.Length > 1 ? parts[1].Trim('[', ']') : null
                        };
                    }
                }
            }
            catch
            {
                // 解析失败，忽略该行
            }

            return null;
        }

        private async Task<object> GetLogLevelStats(DateTime? startDate, DateTime? endDate)
        {
            var stats = new Dictionary<string, int>
            {
                ["Information"] = 0,
                ["Warning"] = 0,
                ["Error"] = 0,
                ["Debug"] = 0
            };

            var logs = await ReadLogFiles(null, startDate, endDate, null, 10000, 0);
            
            foreach (var log in logs)
            {
                if (stats.ContainsKey(log.Level))
                {
                    stats[log.Level]++;
                }
            }

            return new
            {
                Total = logs.Count,
                Levels = stats,
                TimeRange = new
                {
                    Start = startDate,
                    End = endDate
                }
            };
        }
    }

    public class LogEntry
    {
        public DateTime Timestamp { get; set; }
        public string Level { get; set; } = "";
        public string Message { get; set; } = "";
        public string? Exception { get; set; }
        public string? SourceContext { get; set; }
        public string? TraceId { get; set; }
        public string? Properties { get; set; }
    }

    public class TestLogRequest
    {
        [Required]
        public string Level { get; set; } = "Information";
        
        [Required]
        public string Message { get; set; } = "";
        
        public string TestId { get; set; } = Guid.NewGuid().ToString();
    }
}